package com.lank.gateway.exception;

import cn.hutool.core.bean.BeanUtil;
import com.lank.boot.result.Result;
import com.lank.boot.result.enums.SystemEnum;
import com.lank.boot.result.exception.BusinessException;
import com.lank.boot.result.exception.SystemException;
import org.springframework.boot.autoconfigure.web.ErrorProperties;
import org.springframework.boot.autoconfigure.web.WebProperties;
import org.springframework.boot.autoconfigure.web.reactive.error.DefaultErrorWebExceptionHandler;
import org.springframework.boot.web.error.ErrorAttributeOptions;
import org.springframework.boot.web.reactive.error.ErrorAttributes;
import org.springframework.context.ApplicationContext;
import org.springframework.web.reactive.function.server.*;
import org.springframework.web.server.ResponseStatusException;

import java.util.Map;

/**
 * @author root
 */
public class GlobalErrorWebExceptionHandler extends DefaultErrorWebExceptionHandler {

    public GlobalErrorWebExceptionHandler(ErrorAttributes errorAttributes,
                                          WebProperties.Resources resources,
                                          ErrorProperties errorProperties,
                                          ApplicationContext applicationContext) {
        super(errorAttributes, resources, errorProperties, applicationContext);
    }

    @Override
    public Map<String, Object> getErrorAttributes(ServerRequest request, ErrorAttributeOptions options) {

        Throwable error = super.getError(request);

        Result<Object> result;
        if (error instanceof BusinessException) {
            result = Result.ofFail(((BusinessException) error).getCode(), error.getMessage());
        } else if (error instanceof SystemException) {
            result = Result.ofFail(((SystemException) error).getCode(), error.getMessage(), null);
        } else if (error instanceof ResponseStatusException) {
            result = Result.ofFail(((ResponseStatusException) error).getReason(), error.getMessage(), null);
        } else {
            result = Result.ofFail(SystemEnum.EXCEPTION.getCode(), error.getMessage(), null);
        }

        return BeanUtil.beanToMap(result);
    }

    @Override
    protected RouterFunction<ServerResponse> getRoutingFunction(ErrorAttributes errorAttributes) {
        return RouterFunctions.route(RequestPredicates.all(), this::renderErrorResponse);
    }

    @Override
    protected int getHttpStatus(Map<String, Object> errorAttributes) {
        return (int) errorAttributes.get("code");
    }
}
